﻿using SqlSugar;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using DbType = SqlSugar.DbType;

namespace Utility.DB.SqlSugar
{
    /// <summary>
    /// 数据库上下文基类
    /// </summary>
    public class DbContextBase
    {
        private string _connection;
        private DbType _dbType;
        private Action<string, SugarParameter[]> _logExecuting;
        private Action<SqlSugarException> _logError;

        public DbContextBase(string connection, DbType dbType = DbType.SqlServer,
              Action<string, SugarParameter[]> logExecuting = null,
              Action<SqlSugarException> logError = null)
        {
            _connection = connection;
            _dbType = dbType;
            if (logExecuting != null)
                _logExecuting = logExecuting;
            else
                _logExecuting = (sql, p) =>
                {
#if DEBUG
                    Console.WriteLine("【Execute SQL】 " + sql);
                    Console.WriteLine(string.Join(",", p?.Select(it => it.ParameterName + ":" + it.Value)));
#endif
                };

            if (logError != null)
                _logError = logError;
            else
                _logError = ex =>
                {
#if DEBUG
                    // SQL 执行出错
                    Console.WriteLine($"【Execute sql error】 {ex.Sql}  ");
                    Console.WriteLine($"params：{Db.Utilities.SerializeObject(ex.Parametres)}");
#endif
                };
        }

        /// <summary>
        /// 用来处理事务多表查询和复杂的操作
        /// 注意：不能写成静态的，不能写成静态的
        /// </summary>
        public SqlSugarClient Db
        {
            get
            {
                var sqlSugarDB = new SqlSugarClient(new ConnectionConfig()
                {
                    DbType = _dbType,
                    ConnectionString = _connection,
                    InitKeyType = InitKeyType.Attribute,
                    IsAutoCloseConnection = true,
                    AopEvents = new AopEvents
                    {
                        OnLogExecuting = _logExecuting,
                        OnError = _logError
                    }
                });
                //var binPath = AppDomain.CurrentDomain.BaseDirectory;//获取解决方案路径
                //sqlSugarDB.DbFirst.CreateClassFile(binPath, "Model.DBModel");//执行完映射数据实体类
                //执行完数据库就有这个表了
                //sqlSugarDB.CodeFirst.SetStringDefaultLength(200/*设置varchar默认长度为200*/).InitTables(typeof(UserInfo));
                //sqlSugarDB.CodeFirst.SetStringDefaultLength(200/*设置varchar默认长度为200*/).InitTables(typeof(SystemConfigPO));
                //sqlSugarDB.CodeFirst.SetStringDefaultLength(200/*设置varchar默认长度为200*/).InitTables(typeof(SendEmailRecord));
                //Print sql
                sqlSugarDB.Aop.OnLogExecuting = (sql, pars) =>
                {
                    Console.WriteLine(sql + "\r\n" + sqlSugarDB.Utilities.SerializeObject(pars.ToDictionary(it => it.ParameterName, it => it.Value)));
                    Console.WriteLine();
                };
                return sqlSugarDB;
            }
        }
    }

    /// <summary>
    /// 数据库上下文
    /// </summary>
    /// <typeparam name="TPO"></typeparam>
    public class DbContextBase<TPO> : DbContextBase
        where TPO : class, new()
    {
        public DbContextBase(string connection, DbType dbType = DbType.MySql) : base(connection, dbType)
        {
        }

        /// <summary>
        /// 创建数据库表
        /// </summary>
        public virtual void CreateTable()
        {
            Db.CodeFirst.SetStringDefaultLength(200/*设置varchar默认长度为200*/).InitTables(typeof(TPO));
        }

        /// <summary>
        /// 根据主键获取
        /// </summary>
        /// <param name="key">主键值</param>
        /// <returns></returns>
        public virtual TPO GetByKey(object key)
        {
            return Db.Queryable<TPO>().InSingle(key);
        }

        /// <summary>
        /// 根据主键删除
        /// </summary>
        /// <param name="key">主键值</param>
        /// <returns>受影响的行数</returns>
        public virtual int Delete(object key)
        {
            return Db.Deleteable<TPO>().In(key).ExecuteCommand();
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="list">数据集合</param>
        /// <returns></returns>
        public virtual int BatchDelete(List<TPO> list)
        {
            return Db.Deleteable(list).ExecuteCommand();
        }


        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="obj">要更新的对象</param>
        /// <returns>受影响的行数</returns>
        public virtual int Update(TPO obj)
        {
            if (obj == null)
                return 0;
            return Db.Updateable<TPO>(obj).ExecuteCommand();
        }

        /// <summary>
        /// 插入
        /// </summary>
        /// <param name="obj">要插入的新对象</param>
        /// <returns>新插入的Id值</returns>
        public virtual long Insert(TPO obj)
        {
            if (obj == null)
                return 0;
            return Db.Insertable<TPO>(obj).ExecuteReturnBigIdentity();
        }

        /// <summary>
        /// 插入
        /// </summary>
        /// <param name="obj">要插入的新对象</param>
        /// <returns>受影响的行数</returns>
        public virtual int Insert(List<TPO> obj)
        {
            if (obj == null)
                return 0;
            return Db.Insertable<TPO>(obj).ExecuteCommand();
        }

    }
}
